home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / gfx / conv / unmovie.lha / unmovie / unmovie.c < prev   
C/C++ Source or Header  |  1992-06-07  |  9KB  |  409 lines

  1. #include <stdio.h>
  2. #include <iff/ilbm.h>
  3.  
  4. #define ID_DLTA MakeID('D','L','T','A')
  5. #define ID_ANSQ MakeID('A','N','S','Q')
  6. #define ID_FORM MakeID('F','O','R','M')
  7.  
  8. char even[120000];
  9. char odd[120000];
  10.  
  11. char packed[120000];
  12.  
  13. struct {long name;
  14.     long len; } chunk;
  15.  
  16. long    next_form_pos = 0x0C;
  17. long    next_chunk_pos = 0x34;
  18.  
  19. BitMapHeader ilbmbmhd;
  20.  
  21. char    cmap[32*sizeofColorRegister];
  22. int    cmap_len;
  23.  
  24. char    camg[4];
  25. int    camg_len;
  26.  
  27. FILE *in, *out;
  28.  
  29. int frame = 1;
  30.  
  31. struct {
  32.     short uni_flag;
  33.     short y_size;
  34.     short num_blocks; } wall;
  35.  
  36. struct {
  37.     short uni_flag;
  38.     short y_size;
  39.     short x_size;
  40.     short num_blocks; } pile;
  41.  
  42. long    raster_size, plane_size, image_size, insize;
  43.  
  44.  
  45. void
  46. next_form()
  47. {
  48.     int    q;
  49.  
  50.     q=fseek(in, next_form_pos, SEEK_SET);
  51.     if (q!=0) {
  52.         printf("FSEEK fails in 'next_form': dest was %ld\n", next_chunk_pos);
  53.         exit(0);
  54.     }
  55.     fread(&chunk, (size_t)sizeof(chunk), (size_t)1, in);
  56.     next_form_pos = ftell(in) + chunk.len;
  57.     next_chunk_pos = ftell(in)+0x04;
  58. }
  59.  
  60. void
  61. next_chunk()
  62. {
  63.     int    q;
  64.  
  65.     q=fseek(in, next_chunk_pos, SEEK_SET);
  66.     if (q!=0) {
  67.         printf("FSEEK fails in 'next_chunk': dest was %ld\n", next_chunk_pos);
  68.         exit(0);
  69.     }
  70.     fread(&chunk, (size_t)sizeof(chunk), (size_t)1, in);
  71.     next_chunk_pos = ftell(in) + chunk.len;
  72. }
  73.  
  74. delta_proc(buffer)
  75. char *buffer;
  76. {
  77.     short    change_type;
  78.     long    seek_val;
  79.     int    b;
  80.     short    offset;
  81.     long    x, y, z;
  82.     char    charval;
  83.     long    real_offset;
  84.     char    *dest;
  85.  
  86.     while(!feof(in)) {
  87.     fread(&change_type, (size_t)sizeof(short), (size_t)1, in);
  88.  
  89.     switch(change_type) {
  90.     case 0: /* End of DELTA */
  91.         return;
  92.  
  93.     case 1: /* Wall */
  94.         fread(&wall, (size_t)sizeof(wall), (size_t)1, in);
  95.         for (b=0; b<wall.num_blocks; b++) {
  96.         fread(&offset, (size_t)2, (size_t)1, in);
  97.  
  98.         real_offset = ((long)offset/raster_size) * ilbmbmhd.nPlanes;
  99.         real_offset *= raster_size;
  100.         real_offset += offset % raster_size;
  101.  
  102.         for (z=0; z<ilbmbmhd.nPlanes; z++) {
  103.             for (y=0; y<wall.y_size; y++) {
  104.             fread(&charval, (size_t)1, (size_t)1, in);
  105.             dest = buffer;
  106.             dest += z * raster_size*wall.y_size;
  107.             dest += y * raster_size;
  108.             dest += real_offset;
  109.             if (wall.uni_flag == 1)
  110.                 *dest ^= charval;
  111.             else
  112.                 *dest = charval;
  113.             }
  114.         }
  115.  
  116.         /*
  117.          * If we've stopped on an odd boundary, read and throw away
  118.          * another byte.
  119.          */
  120.         seek_val = ftell(in);
  121.         if (seek_val & 0x01L)
  122.             fread(&charval, (size_t)1, (size_t)1, in);
  123.         }
  124.         break;
  125.  
  126.     case 2: /* Pile */
  127.         fread(&pile, (size_t)sizeof(pile), (size_t)1, in);
  128.         for (b=0; b<pile.num_blocks; b++) {
  129.         fread(&offset, (size_t)2, (size_t)1, in);
  130.         real_offset = ((long)offset/raster_size) * ilbmbmhd.nPlanes;
  131.         real_offset *= raster_size;
  132.         real_offset += offset % raster_size;
  133.  
  134.         for (z=0; z<ilbmbmhd.nPlanes; z++) {
  135.             for (y=0; y<pile.y_size; y++) {
  136.             for (x=0; x<pile.x_size; x++) {
  137.                 fread(&charval, (size_t)1, (size_t)1, in);
  138.                 dest = buffer;
  139.                 dest += z * raster_size*pile.y_size;
  140.                 dest += y * raster_size;
  141.                 dest += real_offset + x;
  142.                 if (pile.uni_flag == 1)
  143.                 *dest ^= charval;
  144.                 else
  145.                 *dest = charval;
  146.             }
  147.             }
  148.         }
  149.  
  150.         /*
  151.          * If we've stopped on an odd boundary, read and throw away
  152.          * another byte.
  153.          */
  154.         seek_val = ftell(in);
  155.         if (seek_val & 0x01L)
  156.             fread(&charval, (size_t)1, (size_t)1, in);
  157.         }
  158.         break;
  159.  
  160.     default:
  161.         printf("I seem to have found change_type %d\n", change_type);
  162.         printf("I didn't think there was such a thing!\n");
  163.         exit(1);
  164.         break;
  165.     }
  166.     }
  167. }
  168.  
  169. /*----------------------------------------------------------------------*
  170.  * unpacker.c Convert data from "cmpByteRun1" run compression. 11/15/85
  171.  *
  172.  * By Jerry Morrison and Steve Shaw, Electronic Arts.
  173.  * This software is in the public domain.
  174.  *
  175.  *    control bytes:
  176.  *     [0..127]   : followed by n+1 bytes of data.
  177.  *     [-1..-127] : followed by byte to be repeated (-n)+1 times.
  178.  *     -128       : NOOP.
  179.  *
  180.  * This version for the Commodore-Amiga computer.
  181.  * Manxified and simplified slightly by SDB...
  182.  *----------------------------------------------------------------------*/
  183.  
  184. /* This macro computes the worst case packed size of a "row" of bytes. */
  185. #define MaxPackedSize(rowSize)  ( (rowSize) + ( ((rowSize)+127) >> 7 ) )
  186.  
  187.  
  188. /*----------- UnPackRow ------------------------------------------------*/
  189.  
  190. #define UGetByte()    (*source++)
  191. #define UPutByte(c)    (*dest++ = (c))
  192.  
  193. /* Given POINTERS to POINTER variables, unpacks one row, updating the source
  194.  * and destination pointers until it produces dstBytes bytes. */
  195. int UnPackRow(BYTE **pSource, BYTE **pDest, int srcBytes0, int dstBytes0)
  196. /*    BYTE **pSource, **pDest;  int srcBytes0, dstBytes0; */
  197. {
  198.     register BYTE *source = *pSource;
  199.     register BYTE *dest   = *pDest;
  200.     register int n;
  201.     register BYTE c;
  202.     register int srcBytes = srcBytes0, dstBytes = dstBytes0;
  203.     int error = TRUE;    /* assume error until we make it through the loop */
  204.     WORD minus128 = -128;  /* get the compiler to generate a CMP.W */
  205.  
  206.     while( dstBytes > 0 )  {
  207.     if ( (srcBytes -= 1) < 0 )  goto ErrorExit;
  208.         n = UGetByte();
  209.  
  210.         if (n >= 0) {
  211.         n += 1;
  212.         if ( (srcBytes -= n) < 0 )  goto ErrorExit;
  213.         if ( (dstBytes -= n) < 0 )  goto ErrorExit;
  214.         do {  UPutByte(UGetByte());  } while (--n > 0);
  215.         }
  216.  
  217.         else if (n != minus128) {
  218.         n = -n + 1;
  219.         if ( (srcBytes -= 1) < 0 )  goto ErrorExit;
  220.         if ( (dstBytes -= n) < 0 )  goto ErrorExit;
  221.         c = UGetByte();
  222.         do {  UPutByte(c);  } while (--n > 0);
  223.         }
  224.     }
  225.     error = FALSE;    /* success! */
  226.  
  227.   ErrorExit:
  228.     *pSource = source;  *pDest = dest;
  229.     return(error);
  230. }
  231.  
  232.  
  233. save_block(filename, block)
  234. char    *filename, *block;
  235. {
  236.     FILE *out;
  237.  
  238.     out = fopen(filename, "w");
  239.     chunk.name = ID_FORM;
  240.     chunk.len = image_size + sizeof(ilbmbmhd) + cmap_len + 28;
  241.     if (camg_len)
  242.         chunk.len += camg_len+8;
  243.     fwrite(&chunk, (size_t)sizeof(chunk), (size_t)1, out);
  244.  
  245.     chunk.name = ID_ILBM;
  246.     fwrite(&chunk, (size_t)sizeof(chunk.name), (size_t)1, out);
  247.  
  248.     chunk.name = ID_BMHD;
  249.     chunk.len = sizeof(ilbmbmhd);
  250.     fwrite(&chunk, (size_t)sizeof(chunk), (size_t)1, out);
  251.  
  252.     fwrite(&ilbmbmhd, (size_t)sizeof(ilbmbmhd), (size_t)1, out);
  253.  
  254.     chunk.name = ID_CMAP;
  255.     chunk.len = cmap_len;
  256.     fwrite(&chunk, (size_t)sizeof(chunk), (size_t)1, out);
  257.  
  258.     fwrite(&cmap, (size_t)cmap_len, (size_t)1, out);
  259.  
  260.     if (camg_len) {
  261.         chunk.name = ID_CAMG;
  262.         chunk.len = camg_len;
  263.         fwrite(&chunk, (size_t)sizeof(chunk), (size_t)1, out);
  264.         fwrite(&camg, (size_t)camg_len, (size_t)1, out);
  265.     }
  266.  
  267.     chunk.name = ID_BODY;
  268.     chunk.len = image_size;
  269.     fwrite(&chunk, (size_t)sizeof(chunk), (size_t)1, out);
  270.  
  271.     fwrite(block, (size_t)image_size, (size_t)1, out);
  272.  
  273.     fclose(out);
  274. }
  275.  
  276.  
  277.  
  278.  
  279. /***************************************************************/
  280.  
  281. main(argc, argv)
  282. int argc;
  283. char *argv[];
  284. {
  285.     int    oddframe;
  286.     int    read_size;
  287.     char    *inptr, *outptr;
  288.     long    i, j;
  289.     char    filename[20];
  290.  
  291.  
  292.     if (argc != 2) {
  293.         printf("Usage: unmovie file.movie\n");
  294.         printf("Generates files named f??? representing successive frames\n");
  295.         printf("of the movie, in the same directory.\n");
  296.         printf("For looping movies, the last two frames will be the same as\n");
  297.         printf("the first two.\n");
  298.         printf("For ping-pong movies, the last frame will equal the third\n");
  299.         printf("from last frame.\n");
  300.         exit(0);
  301.     }
  302.  
  303.     in = fopen(argv[1], "r");
  304.     if (in == NULL) {
  305.         printf("Can't seem to open %s for input!\n", argv[1]);
  306.         exit(1);
  307.     }
  308.  
  309.     /*
  310.      * First read in the BMHD
  311.      */
  312.     fseek(in, 0x20, SEEK_SET);
  313.     fread(&ilbmbmhd, (size_t)sizeof(ilbmbmhd), (size_t)1, in);
  314.  
  315.     raster_size = (ilbmbmhd.w+7)/8;
  316.     plane_size = raster_size * ilbmbmhd.h;
  317.     image_size = plane_size * ilbmbmhd.nPlanes;
  318.  
  319.     /*
  320.      * Scan for the BODY. If we encounter a CAMG or a CMAP, store it
  321.      * for later.
  322.      */
  323.     cmap_len = 0;
  324.     camg_len = 0;
  325.     for (;;) {
  326.         next_chunk();
  327.         if (chunk.name == ID_BODY)
  328.             break;
  329.         else if (chunk.name == ID_CMAP) {
  330.             cmap_len = chunk.len;
  331.             fread(&cmap, (size_t)cmap_len, (size_t)1, in);
  332.         }
  333.         else if (chunk.name == ID_CAMG) {
  334.             camg_len = chunk.len;
  335.             fread(&camg, (size_t)camg_len, (size_t)1, in);
  336.         }
  337.     }
  338.  
  339.     /*
  340.      * Read it in.
  341.      */
  342.  
  343.     read_size = fread(packed, (size_t)chunk.len, (size_t)1, in);
  344.     if (read_size != 1) {
  345.         printf("Couldn't read the first image - corrupt file?\n");
  346.         exit(1);
  347.     }
  348.     inptr = packed;
  349.     outptr = even;
  350.     for (outptr = even; outptr<&even[image_size]; ) {
  351.         insize = &packed[chunk.len] - inptr;
  352.         if (ilbmbmhd.compression == cmpByteRun1) {
  353.             if (UnPackRow(&inptr, &outptr, (int)insize,
  354.                 (int)raster_size)) {
  355.                 printf("Some sort of unpacker error!\n");
  356.                 exit(1);
  357.             }
  358.         } else {
  359.             /*
  360.              * Uncompressed input - just copy it
  361.              */
  362.             memcpy(outptr, inptr, raster_size);
  363.             outptr += raster_size;
  364.             inptr += raster_size;
  365.         }
  366.     }
  367.  
  368.  
  369.     /*
  370.      * Store the body out as f001
  371.      */
  372.     printf("Storing frame f001\n");
  373.     ilbmbmhd.compression = cmpNone;
  374.  
  375.     save_block("f001", even);
  376.  
  377.     /*
  378.      * Copy to the "odd" buffer
  379.      */
  380.     memcpy(odd, even, sizeof(even));
  381.  
  382.     next_form();
  383.  
  384.     for (oddframe=FALSE;;oddframe=!oddframe) {
  385.  
  386.         /*
  387.          * We're through if the next chunk is ANSQ
  388.          */
  389.         next_chunk();
  390.         if (chunk.name == ID_ANSQ)
  391.             break;
  392.  
  393.         /*
  394.          * Find the next DLTA
  395.          */
  396.         next_form();
  397.         while (chunk.name != ID_DLTA) {
  398.             next_chunk();
  399.         }
  400.         delta_proc(oddframe ? odd : even);
  401.  
  402.         frame += 1;
  403.         sprintf(filename, "f%03d", frame);
  404.         printf("Storing frame %s\n", filename);
  405.         save_block(filename, oddframe ? odd : even);
  406.     }
  407.     exit(0);
  408. }
  409.